#include "matrix.h"
#include "vector.h"
// enumerations
//--------------
enum EsSolverType
{
 SCG,
 CG,
 FR,
 BF
};// enumerations
//--------------

enum ELinSearchType
{
 Bisection,
 GoldSection,
 Ortogonality,
 Secant
};

class Solve
{
public:
 //Public Methods Declarations

 //Constructors
 Solve(DMatrix _m, DVector _v);
 Solve(DMatrix _m, DVector _v, DVector _x0);
 Solve(DMatrix _m, DVector _v, DVector _x0, double _tol);
 Solve(DMatrix _m, DVector _v, DVector _x0, double _tol, int _maxIter);
 Solve(DMatrix _m, DVector _v, DVector _x0, double _tol, int _maxIter, int _type);
 Solve(DMatrix _m, DVector _v, DVector _x0, double _tol, int _maxIter, int _type, int _linType);

 //Destructor
 ~Solve();

 //Changes the problem's Matrix
 void changeMatrix(DMatrix _m);
 //Changes the problem's Vector
 void changeVector(DVector _v);
 //Changes the problem's Matrix and Vector
 void changeMatrixAndVector(DMatrix _m, DVector _v);
 //Changes the solver's initial point
 void changeInitialPoint(DVector _x0);
 //Changes the solver's tolerance
 void changeTolerance(double _tol);
 //Changes the solver's maximum number of iteration
 void changeMaxIteration(int _maxIter);
 //Changes the solver which will solve the problem
 void changeSolveType(int _type);
 //Changes the linear search
 void changeLinearSearchType(int _linType);

 //Execute the solver
 DVector execute();

private:

 //Private Atributes

 DMatrix m_m;		//System's Matrix
 DVector m_v;		//System's Vector
 DVector m_x0;		//Solver's initial guess
 double m_tol;		//Solver's tolerance
 int m_maxIter;		//Solver's maximum iteration
 int m_type;			// Solver type
 // Solvers:
 //	- 1: Conjugate Gradient Method
 //	- 2: Fletcher-Reeves Method
 //	- 3: BFGS Method
 int m_linType;		//Solver's Linear Search type
 // Linear Search:
 //	- 1: Bisection Method
 //	- 2: Gold Section Method
 //	- 3: Orthogonality Method
 //	- 4: Secant Method
 //	

 DMatrix m_A;		//System's Matrix: ~m_m*m_m (m_m'*m_m)
 DVector m_b;		//System's Matrix: ~m_m*m_b (m_m'*m_b)
 int m_dim;			//System's dimension
 DVector m_dir;		//Search Direction
 //-------------------------------------------------------------------------
 //Private Methods Declarations
 // 
 // Solvers type:

 // Conjugate Gradient Method
 void gradConj(DVector & _x);
 void fletcherReeves(DVector & _x);
 void BFGS(DVector & _x);

 // Linear Search type:
 double bisecao(double _a, double _b);
 double goldSection(double _a, double _b);
 double ortogonalidade();
 double secante();
};